import tornado.ioloop as ioloop

from tornado.options import define
from tornado.options import options
from tornado.options import parse_command_line
from common.db import DB
import sys
import os
import re
import shutil
import unittest
import time
from datetime import datetime
import urls


import config as conf
from importlib import import_module as im

import multiprocessing
import unittest


def run(port, test=0):
    conf.TEST = test
    app = urls.get_application()
    app.listen(port)
    if not conf.TEST:
        print('SERVICE START, PORT:', port)
    ioloop.IOLoop.current().start()


def test(start_dir, pattern='*test.py'):
    suite = unittest.TestLoader().discover(start_dir, pattern=pattern, top_level_dir=".")
    unittest.TextTestRunner(verbosity=2).run(suite)


def main():
    define("cmd", default="runserver", help="command", type=str)
    define("app", default="all", help="apps", type=str)
    define("port", default=8000, help="port", type=int)
    parse_command_line()

    if options.cmd == 'runserver':
        if check_migrations():
            run(options.port)
        else:
            print('exist non-migrate sql script, please run migrate first')

    elif options.cmd == 'test':
        clear_database(test=1)
        process_server = multiprocessing.Process(target=run, kwargs={'port': 9999, 'test': 1})
        process_test = multiprocessing.Process(target=test, kwargs=parse_direction(options.app))
        process_server.start()
        process_test.start()

        while True:
            try:
                if not process_test.is_alive():
                    process_server.terminate()
                    break
                time.sleep(1)
            except Exception as e:
                process_server.terminate()
                process_test.terminate()

    elif options.cmd == 'migrate':
        migrate()

    elif options.cmd == 'startapp':
        create_app(options.app)


def create_app(app_name):
    root = os.path.dirname(os.path.abspath(__file__))
    app_template_path = os.path.join(root, 'app')
    app_path = os.path.join(root, app_name)

    if not os.path.exists(app_path):
        shutil.copytree(app_template_path, app_path)


def migrate():
    regex = re.compile('^[0-9]{4}\.sql$')
    for app in conf.INSTALLED_APPS:
        for database in conf.DATABASES[app]:
            conn = DB(**database)

            # 无条件运行 0000.sql
            path = os.path.join(os.path.dirname(os.path.abspath(__file__)), app, 'migrations')
            cmd = "mysql -u{0} -p{1} {2} < {3}".format(conn.user, conn.password, conn.database, os.path.join(path, '0000.sql'))
            cmd += ' 2>&1 | grep -v "Warning: Using a password" '
            os.system(cmd)

            # 检查所有的以四个数字命名的文件，如果没有运行过，则运行，并更新版本库
            files = os.listdir(path)
            files.sort()
            for file in files:
                if regex.match(file) and file != '0000.sql':
                    sql = "select app, version from migration where app = '{0}' and version = '{1}';".format(app, file[0:4])
                    result = conn.session.execute(sql)
                    if not result.first():
                        cmd_sql = "insert into migration (app, version) values ('{0}', '{1}');".format(app, file[0:4])
                        conn.session.execute(cmd_sql)
                        conn.session.commit()
                        cmd_migrate = "mysql -u{0} -p{1} {2} < {3}".format(conn.user, conn.password, conn.database, os.path.join(path, file))
                        cmd_migrate += ' 2>&1 | grep -v "Warning: Using a password" '
                        print(conn.database, os.path.join(path, file))
                        os.system(cmd_migrate)

            conn.close()


def clear_database(test=0, app_name='all'):
    for app in conf.INSTALLED_APPS:
        # 执行cls.sql
        if app == app_name or app_name == 'all':
            module = im(app)
            conn = DB(**conf.DATABASES[module.database][test])
            path = os.path.join(os.path.dirname(os.path.abspath(__file__)),  app, 'migrations')
            clear_cmd = "mysql -u{0} -p{1} {2} < {3}".format(conn.user, conn.password, conn.database, os.path.join(path, 'cls.sql'))
            clear_cmd += ' 2>&1 | grep -v "Warning: Using a password" '
            os.system(clear_cmd)


def parse_direction(path):
    if path == 'all':
        return {'start_dir': '.'}
    else:
        result = re.match(r'(.*)((?<=\\).*.py)$', path)
        if result != None:
            return {'start_dir': result.group(1), 'pattern': result.group(2)}
        else:
            return {'start_dir': path}


def check_migrations():
    regex = re.compile('^[0-9]{4}\.sql$')
    for app in conf.INSTALLED_APPS:
        module = im(app)
        for database in conf.DATABASES[module.database]:
            conn = DB(**database)
            # 无条件运行 0000.sql
            path = os.path.join(os.path.dirname(os.path.abspath(__file__)), app, 'migrations')
            cmd = "mysql -u{0} -p{1} {2} < {3}".format(conn.user, conn.password, conn.database, os.path.join(path, '0000.sql'))
            # 检查所有的以四个数字命名的文件，如果没有运行过，则运行，并更新版本库
            files = os.listdir(path)
            files.sort()
            for file in files:
                if regex.match(file) and file != '0000.sql':
                    sql = "select app, version from migration where app = '{0}' and version = '{1}';".format(app, file[0:4])
                    result = conn.session.execute(sql)
                    if not result.first():
                        return False
    return True
if __name__ == '__main__':
    main()
